<html>
    <head>
        <title>混入</title>
    </head>
    <body>
        <script>
            // 混入
                    // 一、基础
                            /*
                                混入(Mixing)提供了一种非常灵活的方式，来分发Vue组件中的可复用功能。一个混入独享可以包含任意组件选项。
                                当组件使用"混入"对象时，所有"混入对象的选项"将被"混合"进入该组件本身的选项。
                            */
                                // 例子：
                                       // 定义一个"混入对象"
                                       var myMixin={
                                         created:function(){
                                            this.hello();
                                         },
                                         methods: {
                                            hello:function(){
                                                console.log('hello form mixin!');
                                            }
                                         }
                                       }

                                       // 定义一个实用混入对象的组件
                                       var Component =Vue.extend({
                                          mixins:[myMixin]
                                       })
                                       
                                       var component = new Component();  // ==> "hello from mixin!" 被打印出来


                    // 二、选项合并
                            /*
                                当组件和混入独享含有同名选项时，这些选项将一恰当的方式进行"合并"

                                比如，数据对象在内部进行递归合并，并在发生冲突时一---组件数据优先。
                            */
                                       var mixin ={
                                            data:function(){
                                                return {
                                                    message:'hello',
                                                    foo:'abc'
                                                }
                                            }
                                       }

                                       new Vue({
                                            mixins:[mixin],
                                            data:function(){
                                                return{
                                                    message:'goodbye',
                                                    bar:'def'
                                                }
                                            },
                                            created:function(){
                                                console.log(this.$data)
                                                // ==> {message:"goodbye",foo:"abc",bar:"def"}
                                            }
                                       });

                            // 同名的钩子函数将合并为一个“数组”，因此都将被调用。（另外，混入独享的钩子将在组件自身钩子之前被调用）
                                       var mixin={
                                            created:function(){
                                                console.log('混入对象的created钩子被调用');
                                            }
                                       };

                                       new Vue({
                                            mixings:[mixin],
                                            created:function(){
                                                console.log('组件created钩子被调用');
                                            }
                                       });
                                       // ===> '混入对象的created钩子被调用'
                                       // ===> '组件的created钩子被调用'


                            // 值为对象的选项，例如 methods、components 和 directives 将被合并为同一个对象。(两个对象键名冲突时，去组件独享的键值对)。
                                       var mixin={
                                            methods:{
                                                foo:function(){
                                                    console.log('foo')
                                                },
                                                conflicting:function(){
                                                    console.log('from mixin')
                                                }
                                            }
                                       }

                                       var vm = new Vue({
                                            mixins:[mixin],
                                            methods:{
                                                bar:function(){
                                                    console.log('bar')
                                                },
                                                conflicting:function(){
                                                    console.log('from self')
                                                }
                                            }
                                       })

                                       vm.foo() // ==> "foo"    来自混入对象，实例没有此method
                                       vm.conflicting() // ==> "from self"  混入对象与实例的conflictiong方法冲突，实例的conflicting方法优先级高
                                       vm.bar() // ==> "bar"


                            /*
                                注意:  
                                       Vue.extend() 也是用同样的策略进行合并。
                            */ 


            //  二、全局混入
                            /*
                                混入也可以"全局注册"。 使用的时候要格外小心！ 一旦使用全局混入，它将影响每一个之后创建的Vue实例。

                                当然，如果你使用恰当，这可以用来为"自定义选项"注入处理逻辑。
                            */
                                       // 为自定义的选项  'myOption' 注入处理逻辑。
                                           Vue.mixin({
                                                created:function(){
                                                    // 为 'myOption'选项注入处理逻辑
                                                    var myOption= this.$options.myOption
                                                    if(myOption){
                                                        console.log(myOption)
                                                    }
                                                }
                                           });

                                           new Vue({
                                             myOption:'hello' //  myOption 是一个自定义选型
                                           });

                                           // ==> "hello"
                            /*
                                注意：
                                    请谨慎使用群居混入，因为它会影响每个单独创建的Vue实例(包括第三方组件)
                                    大多数情况下，只应该应用于自定义选项，就像上面示例一样。
                                    推荐奖器最为插件发布，一避免重复应用混入。
                            */
            

            // 三、自定义选项合并策略
                            /*
                                自定义选项将使用 "默认策略" ， 即简单地覆盖已有值。
                                如果想让自定义选项以自定义逻辑合并，可以向 Vue.config.optionMereStrategies 添加一个函数：
                            */
                                    // strategy :英文（战略）   merge: 英文(合并)                                           
                                    Vue.config.optionMergeStrategies.myOption=function(tpVal,fromVal){
                                        // 返回合并后的值
                                    }
                            
                            // 对于多数值为对象选项，可以使用与 methods 相同的合并策略：
                                    var strategies = Vue.config.optionMergeStrategies; // 获取Vue的策略集合对象
                                    strategies.myOption = strategies.methods; // 自定义选项的策略与methods相同

                            // 可以在 Vuex 的混入策略里找到一个更高级的例子：
                                    const merge= Vue.config.optionMergeStrategies.computed; // 获取计算属性的合并策略
                                    Vue.config.optionMergeStrategies.vuex=function(toVal,formVal){
                                        if(!toVal) return formVal
                                        if(!fromVal) return toVal
                                        return {
                                            getters: merge(toVal.getters, fromVal.getters),
                                            state: merge(toVal.state, fromVal.state),
                                            actions: merge(toVal.actions, fromVal.actions)
                                        }
                                    }


        </script>
    </body>
</html>